import { Component, OnInit } from '@angular/core';
import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
// @ts-ignore
import Sortable from 'sortablejs';
import * as echarts from 'echarts';
import { component, topSearchCSS } from './data/component';
import { NzMessageService, NzModalService } from 'ng-zorro-antd';
import { nanoid } from 'nanoid';
import jquery from 'jquery';
import {
  generatorEChartFun,
  generatorFormMapClass,
  generatorInitForm,
  generatorSearchParams,
  generatorUploadFun,
  hasUpload,
  initTsTable,
  initTsTemp
} from './data/geneator-ts';
import {
  generatorCascader,
  generatorCheckBoxGroup,
  generatorDatePicker,
  generatorEChart,
  generatorInput,
  generatorInputNumber,
  generatorRadioGroup,
  generatorRow,
  generatorSelect,
  generatorSwitch,
  generatorTable,
  generatorTimePicker,
  generatorTreeSelect,
  generatorUpload,
  timePickerFormat
} from './data/generator-html';
import Prism from 'prismjs';
import { generatorTopSearchHtml, generatorTopSearchTs } from './data/generator-top-search-html';
import { crudCode } from './data/crud';
import { generatorComponentInterface, generatorComponentMethod, getSwaggerData } from './utils/swagger-config';
import { echartsMethod } from './data/echarts-method';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent  implements  OnInit {
  componentList = [
    ...component
  ];
  widgetList = [] as any;
  visible = false;
  tabList = ['HTML', 'CSS', 'TS', 'SERVICE_TS'];
  activeTab = 'HTML';
  codeTempMap = {
    htmlTemp: '',
    htmlTempOrigin: '',
    tsTemp: '',
    tsTempOrigin: '',
    serviceTsTemp: '',
    serviceTsTempOrigin: '',
    topSearchHtml: '',
    topSearchHtmlOrigin: '',
    topSearchCSS: Prism.highlight(topSearchCSS, Prism.languages.css , 'css'),
    topSearchCSSOrigin: topSearchCSS,
    topSearchTs: '',
    topSearchTsOrigin: ''
  };
  selectedComponent = {} as any;
  optionName = '';
  configFieldVisible = false;
  modalType = '';
  crudVisible = false;
  crudCode = Prism.highlight(crudCode, Prism.languages.javascript , 'javascript');
  curdCodeOrigin = crudCode;
  openSwaggerConfig = false;
  swaggerUrl = '';
  matchUrl = '';
  swaggerData = {};
  swaggerVisible = false;
  isLoading = false;
  compChartRef = null;
  chartOption = {};
  constructor(
    private message: NzMessageService,
    private modal: NzModalService
  ) {
  }
  ngOnInit(): void {
    this.initSort();
  }

  initSort() {
    new Sortable(document.querySelector('.component-list'), {
      group: {
        name: 'shared',
        pull: 'clone'
      },
      animation: 150,
      sort: false
    });
    new Sortable(document.querySelector('.center-wrapper'), {
      group: {
        name: 'shared',
      },
      animation: 150,
      onAdd: (e: any) => this.addCenterWrapper(e)
    });
  }

  object2Json(obj: any) {
    return JSON.stringify(obj);
  }

  addCenterWrapper(e: any) {
    const dataJson = JSON.parse(e.item.getAttribute('data-json'));
    dataJson.key = nanoid();
    if (dataJson.name !== 'Row') {
      dataJson.field = nanoid().slice(0, 6);
    } else {
      dataJson.nanoid = nanoid().slice(0, 6);
    }
    const componentItem = document.querySelector('.center-wrapper .component-item');
    // @ts-ignore
    componentItem.remove();
    if (dataJson.name === 'EChart') {
      if (this.widgetList.length) {
        this.message.error('添加EChart组件时，请先清空其他组件');
        return;
      }
      let echartNum = 0;
      this.widgetList.map((item, i) => {
        if (item.name === 'EChart') {
          echartNum += 1;
        }
      });
      if (echartNum >= 1) {
        this.message.error('echart组件只能有一个');
        return false;
      }
    }
    this.widgetList.push(dataJson);
    this.selectedComponent = dataJson;
    if (dataJson.name === 'EChart') {
      setTimeout(() => {
        this.renderChart();
      }, 200);
    }
    if (dataJson.name !== 'Row') {
      return;
    }
    setTimeout(() => {
      const row = document.querySelectorAll('.widget-row');
      const i = row.length - 1;
      new Sortable(row[i], {
        group: {
          name: 'shared',
        },
        animation: 150,
        onAdd: (e: any) => {
          const childrenJson = JSON.parse(e.item.getAttribute('data-json'));
          childrenJson.key = nanoid();
          const dataNanoid = e.target.getAttribute('data-nanoid');
          const index = this.widgetList.findIndex((item: any) => item.nanoid === dataNanoid);
          childrenJson.field = nanoid().slice(0, 6);
          if (this.widgetList[index].children) {
            this.widgetList[index].children.push(childrenJson);
          }
          // tslint:disable-next-line:no-shadowed-variable
          const componentItem = document.querySelector('.center-wrapper .widget-row .component-item');
          if (componentItem) {
            // @ts-ignore
            componentItem.remove();
          }
        }
      });
    });
  }

  clickTab(val: string) {
    this.activeTab = val;
  }

  clickComponent(data: any, e: any) {
    e.stopPropagation();
    e.preventDefault();
    this.selectedComponent = data;
  }

  clickCopy(i: number) {
    const data = this.widgetList[i];
    if (data.name === 'EChart') {
      return;
    }
    const newData = JSON.parse(JSON.stringify(data));
    newData.field = nanoid().slice(0, 6);
    this.widgetList.push(newData);
  }

  clickSubCopy(i: number, k: number) {
    const data = this.widgetList[i].children[k];
    const newData = JSON.parse(JSON.stringify(data));
    newData.field = nanoid().slice(0, 6);
    this.widgetList[i].children.push(newData);
  }

  clickDelete(i: number) {
    this.widgetList.splice(i, 1);
  }

  clickSubDelete(i: number, k: number) {
    this.widgetList[i].children.splice(k, 1);
  }

  clickViewCode() {
    this.codeTempMap.htmlTemp = '';
    this.codeTempMap.tsTemp = initTsTemp(this.widgetList);
    const tableC = this.widgetList.find((item: any) => item.name === 'Table');
    if (tableC) {
      this.codeTempMap.tsTemp += initTsTable(this.widgetList);
    }
    this.widgetList.map((item: any) => {
      // @ts-ignore
      const map = {
        Input: () => generatorInput(item),
        Row: () => generatorRow(item),
        Cascader: () => generatorCascader(item),
        CheckboxGroup: () => generatorCheckBoxGroup(item),
        DatePicker: () => generatorDatePicker(item),
        InputNumber: () => generatorInputNumber(item),
        RadioGroup: () => generatorRadioGroup(item),
        Select: () => generatorSelect(item),
        Switch: () => generatorSwitch(item),
        TimePicker: () => generatorTimePicker(item),
        TreeSelect: () => generatorTreeSelect(item),
        Upload: () => generatorUpload(item),
        Table: () => generatorTable(item),
        EChart: () => generatorEChart(),
      };
      // @ts-ignore
      if (map[item.name]) {
        // @ts-ignore
        this.codeTempMap.htmlTemp += map[item.name]();
      }
    });
    // 删除空行
    this.codeTempMap.htmlTemp = this.codeTempMap.htmlTemp.replace(/\n\s*\n/g, '\n');
    this.codeTempMap.tsTemp += generatorInitForm(this.widgetList);
    if (this.widgetList.length && this.widgetList[0].name === 'EChart') {
      this.codeTempMap.tsTemp += generatorEChartFun(this.chartOption);
    }
    if (this.openSwaggerConfig) {
      this.codeTempMap.tsTemp += generatorComponentMethod();
    }
    if (hasUpload(this.widgetList)) {
      this.codeTempMap.tsTemp += generatorUploadFun(this.widgetList);
    }
    this.codeTempMap.tsTemp += generatorFormMapClass(this.widgetList);
    if (tableC) {
      this.codeTempMap.tsTemp += generatorSearchParams(this.widgetList);
    }
    if (this.openSwaggerConfig) {
      this.codeTempMap.tsTemp += generatorComponentInterface();
    }
    this.codeTempMap.htmlTempOrigin = this.codeTempMap.htmlTemp;
    this.codeTempMap.tsTempOrigin = this.codeTempMap.tsTemp;
    this.codeTempMap.htmlTemp = Prism.highlight(this.codeTempMap.htmlTemp, Prism.languages.html, 'html');
    this.codeTempMap.tsTemp = Prism.highlight(this.codeTempMap.tsTemp, Prism.languages.javascript , 'javascript');
    this.tabList = ['HTML', 'TS'];
    if (this.openSwaggerConfig) {
      this.tabList.push('SERVICE_TS');
    }
    this.activeTab = 'HTML';
    this.visible = true;
    this.modalType = 'normal';
  }

  clickViewTopSearchCode() {
    this.tabList = ['HTML', 'CSS', 'TS'];
    this.activeTab = 'HTML';
    if (this.widgetList.length === 0) {
      this.message.error('生成顶部代码时，至少需要有一个组件');
      return;
    }
    if (this.widgetList[0].name !== 'Row') {
      this.message.error('生成顶部代码时，第一个组件必须是Row组件');
      return;
    }
    this.codeTempMap.topSearchHtml = generatorTopSearchHtml([this.widgetList[0]], this.selectedComponent);
    this.codeTempMap.topSearchHtmlOrigin = generatorTopSearchHtml([this.widgetList[0]], this.selectedComponent);
    this.codeTempMap.topSearchTs = generatorTopSearchTs([this.widgetList[0]], this.selectedComponent);
    this.codeTempMap.topSearchTsOrigin = generatorTopSearchTs([this.widgetList[0]], this.selectedComponent);
    this.codeTempMap.topSearchHtml = Prism.highlight(this.codeTempMap.topSearchHtml, Prism.languages.html, 'html');
    this.codeTempMap.topSearchTs = Prism.highlight(this.codeTempMap.topSearchTs, Prism.languages.javascript , 'javascript');
    this.visible = true;
    this.modalType = 'top-search';
  }

  setSwaggerCode() {
    this.swaggerVisible = true;
  }

  clickViewCrudCode() {
    this.crudVisible = true;
  }

  clearCode() {
    this.modal.confirm({
      nzTitle: '确定要清空吗？',
      nzContent: '此操作会清空所有组件，是否继续？',
      nzOnOk: () => {
        this.widgetList = [];
        this.selectedComponent = {};
      }
    });
  }

  clickCopyCode(type: string) {
    const map = {
      html: this.modalType === 'normal' ? this.codeTempMap.htmlTempOrigin : this.codeTempMap.topSearchHtmlOrigin,
      css: this.codeTempMap.topSearchCSSOrigin,
      ts: this.modalType === 'normal' ? this.codeTempMap.tsTempOrigin : this.codeTempMap.topSearchTsOrigin,
      crud: this.curdCodeOrigin,
      service_ts: this.codeTempMap.serviceTsTempOrigin
    };
    const copyText = map[type];
    const contentArea = document.querySelector('.content-area');
    // @ts-ignore
    contentArea.value = copyText;
    // @ts-ignore
    contentArea.select();
    document.execCommand('copy');
    this.message.success('复制成功');
  }

  async copyTextToClipboard(text: string) {
    try {
      // @ts-ignore
      await navigator.clipboard.writeText(text);
      this.message.success('复制成功');
    } catch (err) {
      console.log(err);
      this.message.error('复制失败');
    }
  }

  confirmAddOption() {
    this.selectedComponent.options.push({
      label: this.optionName,
      value: this.optionName,
      checked: false
    });
    this.optionName = '';
  }

  removeOption(i: number) {
    this.selectedComponent.options.splice(i, 1);
  }

  timePickerFormat(data) {
    return timePickerFormat(data);
  }

  clickConfigField() {
    this.configFieldVisible = true;
  }

  dropField(e: CdkDragDrop<string[]>) {
    moveItemInArray(this.selectedComponent.columns, e.previousIndex, e.currentIndex);
  }

  clickDeleteColumns(index: number) {
    this.selectedComponent.columns.splice(index, 1);
  }

  clickAddColumns() {
    this.selectedComponent.columns.push({
      title: '',
      field: '',
      isSort: false,
      showFilter: false,
      customFilter: false,
      filterMultiple: true
    });
  }

  changeFilter(data, value, type) {
    if (value) {
      if (type === 'showFilter') {
        data.customFilter = false;
      }
      if (type === 'customFilter') {
        data.showFilter = false;
      }
    }
  }

  clickRequestSwagger() {
    if (!this.swaggerUrl) {
      this.message.error('请输入swagger地址');
      return;
    }
    this.isLoading = true;
    jquery.ajax(this.swaggerUrl, {
      timeout: 5000
    }).then(res => {
      if (res) {
        this.isLoading = false;
        this.message.success('请求成功');
        this.swaggerData = res;
        this.generatorApiCode();
      }
    }).catch(e => {
      this.isLoading = false;
      this.message.error(e.statusText + ',' + '请检查swagger地址是否正确');
    });
  }

  generatorApiCode() {
    if (!this.matchUrl) {
      return;
    }
    this.codeTempMap.serviceTsTempOrigin = getSwaggerData(this.swaggerData, this.matchUrl);
    this.codeTempMap.serviceTsTemp = Prism.highlight(this.codeTempMap.serviceTsTempOrigin, Prism.languages.javascript , 'javascript');
  }

  renderChart() {
    const chartComp = document.querySelector('.chart-comp');
    this.compChartRef = echarts.init(chartComp);
    this.chartOption = {
      backgroundColor: this.selectedComponent.backgroundColor,
      legend: {
        show: true,
      },
      xAxis: {
        type: 'category',
        data: ['MonMonMonMonMonMonMon', 'TueTueTueTueTueTueTue',
          'WedWedWedWedWedWedWedWed', 'ThuThuThuThuThuThuThuThu',
          'FriFriFriFriFriFriFriFriFri', 'SatSatSatSatSatSatSat',
          'SunSunSunSunSunSunSunSun']
      },
      tooltip: {
        trigger: 'axis'
      },
      yAxis: {
        type: 'value'
      },
      series: [
        {
          name: 'test1',
          data: [150, 230, 224, 218, 135, 147, 260],
          type: 'bar',
        },
        {
          name: 'test2',
          data: [320, 332, 301, 334, 390, 330, 320],
          type: 'bar'
        }
      ]
    };
    this.compChartRef.setOption(this.chartOption);
  }

  changeEChartType(field: string) {
    this.chartOption = echartsMethod(field, this.chartOption, this.selectedComponent);
    this.compChartRef.clear();
    this.compChartRef.setOption(this.chartOption);
  }

}

